package no.ntnu.fp.console;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

import javax.swing.JOptionPane;

import no.ntnu.fp.comparators.CompareRoomReservations;
import no.ntnu.fp.controllers.*;
import no.ntnu.fp.model.Room;
import no.ntnu.fp.storage.DBConnection;
import no.ntnu.fp.views.AppointmentView;
import acm.program.ConsoleProgram;

public class Options {
	ConsoleProgram caller;
	AppointmentController appointmentController;
	MeetingController meetingController;
	MessageController messageController;
	UserController userController;
	String username;
	CompareRoomReservations crr;
	AppointmentView appointmentView;

	public Options(ConsoleProgram caller) {
		this.caller = caller;
		this.userController = new UserController(this);
		this.meetingController = new MeetingController(this);
		this.messageController = new MessageController(caller);
		this.appointmentController = new AppointmentController(this);
		this.crr = new CompareRoomReservations();
		this.appointmentView = new AppointmentView(this);
	}
	
	public boolean welcomeWantToLogIn() {
		String[] choices = {"Ja", "Nei"};
		int response = showChoices(choices,"Hei, og velkommen til denne kalenderen. Vil du logge inn?", "Innlogging");
		return (response == 0) ? true : false;
	}
	
	public void exit() {
		System.exit(0);
	}
	
	public String logIn() {
		while (true) {
			String username = inputDialog("Skriv inn brukernavn: ");
			String password = inputDialog("Skriv inn passord: ");
			String[] loginDetails = {username, password};
			if (userController.isValid(loginDetails))
					return username;
			messageDialog("Ugyldig brukernavn og/eller passord\nBrukernavn: " + username + " " + "Passord: " + password + "\nProv pa nytt!");
		}
	}
	
	private String inputDialog(String message) {
		return JOptionPane.showInputDialog(message);
	}

	public void setCurrentUser(String username) {
		this.username = username;
	}

	public boolean hasMessages(String username) {
		return messageController.hasMoteinnkallinger(username);
	}
	
	public boolean hasMessageToMeetingLeader(String userName) {
		return messageController.hasMessageToMeetingLeader(userName);
	}
	
	public void retrieveMessage(String username) {
		messageController.retrieveMessage(username);
	}

	public void showOfflineMessages(String username) {
		messageController.showOfflineMessages(username);
	}
	
	public boolean hasMessage(String username) {
		return messageController.hasMessage(username);
	}
	
	public void showMessage(String username) {
		messageController.showMessage(username);
	}

	public void showUserAppointments(String username) {
		appointmentController.showUserAppointments(username);
	}
	
	public void messageDialog(String message) {
		JOptionPane.showMessageDialog(caller, message);
	}
	
	public static int intInputDialog(String message, int defaults) {
		return Integer.parseInt(JOptionPane.showInputDialog(message, defaults));
	}

	public static String inputDialog(String message, String defaults) {
		return JOptionPane.showInputDialog(message, defaults);
	}

	public static int showChoices(String[] choices, String message, String title) {
		boolean empty = false;
		if (choices.length == 0) {
			String[] newChoices = {"Tilbake"};
			choices = newChoices;
			empty = true;
		}

		int input = JOptionPane.showOptionDialog(
				null, message, title            
				, JOptionPane.YES_NO_OPTION 
				, JOptionPane.PLAIN_MESSAGE
				, null, choices, "Avtale"
				);

		if (empty) {
			return -1;
		}
		return input;
	}


	public void printMenu() {
		if (!isMoteleder(username)) {
			final int createUser = 0, createAppointment = 1, meeting = 2, showAllAppointments = 3, editAppointment = 4, deleteAppointment = 5, ownCalendar = 6, logout = 7; //, avtaleView = 8;
		
			String[] choices = {"Bruker", "Lage Avtale", "Mote", "Alle avtaler", "Endre avtale", "Slette avtale", "Egen kalender", "Logg Ut"}; //, "Avtale View"};
			int input = showChoices(choices,"Hva vil du gjore?", "Meny");
	
			switch (input) {
			case(createUser): createUser(); break;
			case(createAppointment): createAppointment(); break;
			case(meeting): createMeeting(); break;
			case(showAllAppointments): showAllAppointments(); break;
			case(editAppointment): actionEditFromSelection(); break;
			case(deleteAppointment): actionDeleteFromSelection(); break;
			case(ownCalendar): showUserAppointments(); break;
			case(logout): caller.run(); break;
			//case(avtaleView): appointmentView.setUsername(username); appointmentView.run(); break;
			}
		}
		else {
			final int createUser = 0, createAppointment = 1, meeting = 2, showAllAppointments = 3, editAppointment = 4, deleteAppointment = 5, ownCalendar = 6, changeMeeting = 7, cancelMeeting = 8, logout = 9;
			
			String[] choices = {"Bruker", "Lage Avtale", "Mote", "Alle avtaler", "Endre avtale", "Slette avtale", "Vis egen kalender", "Endre moteinnkalling", "Avlys mote", "Logg ut"};
			int input = showChoices(choices, "Hva vil du gjore?", "Meny");
			
			switch (input) {
			case(createUser): createUser(); break;
			case(createAppointment): createAppointment(); break;
			case(meeting): createMeeting(); break;
			case(showAllAppointments): showAllAppointments(); break;
			case(editAppointment): actionEditFromSelection(); break;
			case(deleteAppointment): actionDeleteFromSelection(); break;
			case(ownCalendar): showUserAppointments(); break;
			case(changeMeeting): {
				String[] choices2 = findMeetingsExceptionHandler(username);
				int input2 = showChoices(choices2, "Velg mote du vil endre", "Endre moteinnkalling");
				int aID = findAIDExceptionHandler(input2, username);
				messageController.changeMoteinnkalling(aID);
				break;
			}
			case(cancelMeeting): {
				String[] choices2 = findMeetingsExceptionHandler(username);
				int input2 = showChoices(choices2, "Velg mote du vil avlyse", "Avlyse mote");
				int aID = findAIDExceptionHandler(input2, username);
				messageController.cancelMeeting(aID);
				break;
			}
			case(logout): caller.run(); break;
			}
		}
	}
	
	private boolean isMoteleder(String username) {
		DBConnection db = new DBConnection();
		String query = "select AvtaleID from OppretterMote " +
				"where Moteleder = " + "\"" + username + "\"";
		ResultSet rs = db.makeSingleQuery(query);
		try {
			if (rs.next()) {
				return true;
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return false;
	}
	
	private int findAIDExceptionHandler(int index, String username) {
		try {
			return findAID(index, username);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return -1;
	}
	
	private int findAID(int index, String username) throws SQLException {
		DBConnection db = new DBConnection();
		ArrayList<Integer> aIDs = new ArrayList<Integer>();
		String query = "select Avtale.AvtaleID " +
				"from Avtale,OppretterMote " +
				"where Avtale.AvtaleID = OppretterMote.AvtaleID " +
				"and Moteleder = " + "\"" + username + "\"";
		ResultSet rs = db.makeSingleQuery(query);
		while (rs.next()) {
			aIDs.add(rs.getInt("AvtaleID"));
		}
		return aIDs.get(index);
	}
	
	private String[] findMeetingsExceptionHandler(String username) {
		try {
			return findMeetings(username);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	private String[] findMeetings(String username) throws SQLException {
		DBConnection db = new DBConnection();
		ArrayList<String> meetings = new ArrayList<String>();
		String query = "select Dato, Starttidspunkt, Sluttidspunkt, Beskrivelse " +
				"from Avtale,OppretterMote " +
				"where Avtale.AvtaleID = OppretterMote.AvtaleID" +
				" and Moteleder = " + "\"" + username + "\"";
		ResultSet rs = db.makeSingleQuery(query);
		while (rs.next()) {
			String avtaleStreng = rs.getString("Dato") + ",   " + "Start: " + rs.getString("Starttidspunkt") + ",   " + "Slutt: " + rs.getString("Sluttidspunkt") + ",   " + rs.getString("Beskrivelse");
			meetings.add(avtaleStreng);
		}
		
		String[] avtaleStrengArray = new String[meetings.size()];
		meetings.toArray(avtaleStrengArray);
		db.closeConnection();
		return avtaleStrengArray;
	}
	
	private void createUser() {
		String username = JOptionPane.showInputDialog("Skriv inn brukernavn: ");
		String password = JOptionPane.showInputDialog("Skriv inn passord: ");
		String firstname = JOptionPane.showInputDialog("Skriv inn fornavn: ");
		String surname = JOptionPane.showInputDialog("Skriv inn etternavn: ");
		String birthdate = JOptionPane.showInputDialog("Skriv inn fodselsdato: ");
		
		userController.addUserToDatabase(username, password, firstname, surname, birthdate);
	}
	
	protected void createAppointment() {
		String date= inputDialog("Skriv inn avtaledato (maks 6 tegn):", "311212");
		String start = inputDialog("Skriv inn starttidspunkt for avtale:", "00.00");
		String stop = inputDialog("Skriv inn sluttidspunkt for avtale:", "00.00");
		String description = inputDialog("Skriv inn avtalebeskrivelse:");
		int numberOfParticipants= Integer.parseInt(inputDialog("Skriv inn totalt antall deltakere:"));
		String place;
		
		String bookRoom = inputDialog("Onsker du a reservere moterom? (Ja eller Nei)");
		if (bookRoom.equalsIgnoreCase("Ja")) {
			place = printRoomsExceptionHandler(numberOfParticipants, date, start, stop);
		}
		else
			place = inputDialog("Skriv inn sted for mote: ");

		appointmentController.actionCreate(username, date, start, stop, description, place, numberOfParticipants);
	}
	
	private void createMeeting() {
		String[] users = userController.getUserListWithoutPasswords();

		String date= JOptionPane.showInputDialog("Skriv inn motedato:", "010112");
		String start= JOptionPane.showInputDialog("Skriv inn starttidspunkt for m�te:", "00.00");
		String end= JOptionPane.showInputDialog("Skriv inn sluttidspunkt for mote:", "23.59");
		String description = JOptionPane.showInputDialog("Skriv inn beskrivelse for moteinnkallinga: ");
		ArrayList<String> usersInvited = getUsersInvited(users);
		int numberOfParticipants= Integer.parseInt(inputDialog("Skriv inn totalt antall deltakere:"));
		boolean hasBookedRoom = false;
		String place;
		
		String bookRoom = inputDialog("Onsker du a reservere moterom? (Ja eller Nei)");
		if (bookRoom.equalsIgnoreCase("Ja")) {
			place = printRoomsExceptionHandler(numberOfParticipants, date, start, end);
			hasBookedRoom = true;
		}
		else
			place = inputDialog("Skriv inn sted for mote: ");
		
		
		meetingController.createMeeting(usersInvited, username, date, start, end, place, description, hasBookedRoom);
	}
	
	

	private String printRoomsExceptionHandler(int numberOfParticipants,
			String date, String start, String end) {
		try {
			return printRooms(numberOfParticipants,date,start,end);
		} catch (SQLException e) {
			e.printStackTrace();
			return null;
		}
	}

	public String printRooms(int str, String date, String start, String stop) throws SQLException {
		
		String[] rooms = Room.getAllRoomsLargerThan(str);
		ArrayList<String> roomsFinal = new ArrayList<String>();
		
		//m� luke ut rom som allerede er reservert
		String timeString = date + " " + start + " " + stop;
		
		for (int i = 0; i < rooms.length; i++) {
			DBConnection db = new DBConnection();
			String query = "select Dato, Starttidspunkt, Sluttidspunkt from Avtale " +
					"where Sted = " + "\"" + rooms[i] + "\"" + "";
			ResultSet rs = db.makeSingleQuery(query);
			ArrayList<String> timeStrings = new ArrayList<String>();
			while (rs.next()) {
				String dato = rs.getString("Dato");
				String starttidspunkt = rs.getString("Starttidspunkt");
				String sluttidspunkt = rs.getString("Sluttidspunkt");
				String timeString2 = dato + " " + starttidspunkt + " " + sluttidspunkt;
				timeStrings.add(timeString2);
			}
			//hvis rom ikke allerede er reservert legges det inn i roomsFinal
			int compared = -1;
			for (int j = 0; j < timeStrings.size(); j++) {
				compared = crr.compare(timeString, timeStrings.get(j));
				if (compared == 0) { //er allerede reservert
					break; //bryter ut av lokka, ingen vits i a sjekke flere avtaler
				}
			}
			if (compared == -1) { //ikke reservert
				roomsFinal.add(rooms[i]);
			}
		}
		//konverter roomsFinal til roomsFinalArray
		String[] roomsFinalArray = new String[roomsFinal.size()];
		roomsFinal.toArray(roomsFinalArray);
		
		int input = Options.showChoices(roomsFinalArray, "Hvilket moterom vil du reservere?", "Moterom");
		
		return roomsFinalArray[input];
	}
	
	private ArrayList<String> getUsersInvited(String[] users) {
		ArrayList<String> usersInvited = new ArrayList<String>();
		String temp;
		do {
			temp = getUser(users);
			if (temp != null)
				usersInvited.add(temp);
		} while(temp != null);
		
		return usersInvited;
	}
	
	private String getUser(String[] users) {
		int teller = 1;
		String[] choices = new String[users.length];
		choices[0] = "Avslutt";
		for (int i = 0; i < users.length; i++) {
			if (!(users[i].equalsIgnoreCase(username))) {
				choices[teller] = users[i];
				teller++;
			}
		}
		

		int input = Options.showChoices(choices, "Hvilken bruker vil du ha med?", "Meny");
		
		if (input == 0)
			return null;
		else
			return choices[input];
	}

	private void showAllAppointments() {
		appointmentController.showAllAppointments();
	}
	
	protected void actionEditFromSelection() {
		appointmentController.actionEditFromSelection(username);
	}

	protected void actionDeleteFromSelection() {
		appointmentController.actionDeleteFromSelection(username);
	}
	
	private void showUserAppointments() {
		appointmentController.showUserAppointments(username);
	}
}